#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <input_manager.h>
#include <sys/time.h>  // 用于 gettimeofday()
#include <stdio.h>      // 用于 snprintf()

#define SERVER_PORT 8888

static int g_iSocketServer; // 定义全局变量，在多个函数中都会用到这个变量

// 网络输入设备初始化
static int NI_InputDeviceInit(void){

    struct sockaddr_in tSocketServerAddr;
    int iRet;

    // 创建套接字
	g_iSocketServer = socket(AF_INET, SOCK_DGRAM, 0);
	if (-1 == g_iSocketServer)
	{
		printf("socket error!\n");
		return -1;
	}

	// 初始化服务器地址结构（后面bind会用到）
	tSocketServerAddr.sin_family      = AF_INET;
	tSocketServerAddr.sin_port        = htons(SERVER_PORT);  /* host to net, short */
 	tSocketServerAddr.sin_addr.s_addr = INADDR_ANY;
	memset(tSocketServerAddr.sin_zero, 0, 8);

	// 将服务器套接字与指定的地址（tSocketServerAddr）绑定
	iRet = bind(g_iSocketServer, (const struct sockaddr *)&tSocketServerAddr, sizeof(struct sockaddr));
	if (-1 == iRet)
	{
		printf("bind error!\n");
		return -1;
	}

    return 0; // 初始化成功返回0
}



// 从网络输入设备获取网络输入事件
static int NI_GetInputEvent(PInputEvent ptInputEvent){

    struct sockaddr_in tSocketClientAddr;
	int iRecvLen;
	char ucRecvBuf[1000];
    unsigned int iAddrLen = sizeof(struct sockaddr);
    
    iRecvLen = recvfrom(g_iSocketServer, ucRecvBuf, 999, 0, (struct sockaddr *)&tSocketClientAddr, &iAddrLen);
    
    if (iRecvLen > 0)
    {
        ucRecvBuf[iRecvLen] = '\0';
        ptInputEvent->iType = INPUT_TYPE_NET;
        // 填充时间戳
        gettimeofday(&ptInputEvent->tTime, NULL);
        // 填充字符串数据
        strncpy(ptInputEvent->str, ucRecvBuf, 1000);
        ptInputEvent->str[999] = '\0';
        return 0;
    }

    else
    {
        return -1;
    }
}



// 关闭套接字，退出网络输入设备
static int NI_InputDeviceExit(void){

    close(g_iSocketServer);
	return 0;

}




// 声明一个InputDevice结构体，用来描述网络输入设备
static struct InputDevice g_tNetInput = {
    
    .name = "NetInput",
    .InputDeviceInit = NI_InputDeviceInit,
    .GetInputEvent = NI_GetInputEvent,
    .InputDeviceExit = NI_InputDeviceExit,

};


void RegisterNItoDeviceList(void)
{

	// g_tNetInput调用注册InputEvent函数
	RegisterInputDevice(&g_tNetInput);
}


#if 0

// 测试网络输入
int main(int argc, char **argv)
{
    InputEvent tInputEvent_tmp; // 定义一个tmp的PInputEvent用于测试
    int ret;
    
    // 初始化
    g_tNetInput.InputDeviceInit();

    while (1)
    {
        ret = g_tNetInput.GetInputEvent(&tInputEvent_tmp);
        if (ret)
        {
            printf("GetInputEvent failed.\n");
            return -1;
        }
        else
        {
            printf("iType : %d\n", tInputEvent_tmp.iType);
            // 打印字符串数据
            printf("str   : %s\n", tInputEvent_tmp.str);
        }
    }
    

}

#endif
